package com.dongdongshop.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.dongdongshop.common.SeckillConstant;
import com.dongdongshop.data.content.IdWorker;
import com.dongdongshop.mapper.seckill.TbSeckillGoodsMapper;
import com.dongdongshop.mapper.seckill.TbSeckillOrderMapper;
import com.dongdongshop.pojo.seckill.TbSeckillGoods;
import com.dongdongshop.pojo.seckill.TbSeckillGoodsExample;
import com.dongdongshop.pojo.seckill.TbSeckillOrder;
import com.dongdongshop.service.seckill.SeckillServiceI;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Service
public class SeckillServiceImpl implements SeckillServiceI {

    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private TbSeckillGoodsMapper seckillGoodsMapper;
    @Resource
    private TbSeckillOrderMapper seckillOrderMapper;
    @Autowired
    private IdWorker idWorker;
    @Resource
    private RocketMQTemplate rocketMQTemplate;


    @Override
    public List<TbSeckillGoods> findSeckillList() {
         redisTemplate.setValueSerializer(new StringRedisSerializer());
        //从redis中查询所有要秒杀的商品
        List<TbSeckillGoods> seckillList = redisTemplate.boundHashOps(SeckillConstant.SECKILLLIST).values();//查询所有
        //2.判断是否有数据 如果没有查询mysql
        if(seckillList == null || seckillList.size() <= 0){
            TbSeckillGoodsExample example = new TbSeckillGoodsExample();
            TbSeckillGoodsExample.Criteria criteria = example.createCriteria();
            criteria.andStatusEqualTo("1");//审核已通过
            criteria.andStartTimeLessThanOrEqualTo(new Date());//秒杀开始时间小于或者等于当前时间
            criteria.andEndTimeGreaterThanOrEqualTo(new Date());//秒杀结束时间大于或者等于当前时间
            criteria.andStockCountGreaterThan(0);//库存大于0
            seckillList = seckillGoodsMapper.selectByExample(example);
            //3.将mysql数据同步到redis
            for (TbSeckillGoods seckillGoods : seckillList) {
                redisTemplate.boundHashOps(SeckillConstant.SECKILLLIST).put(seckillGoods.getId(),seckillGoods);
                //秒杀预减库存
//                redisTemplate.boundValueOps(seckillGoods.getId()).set(seckillGoods.getStockCount());
                redisTemplate.boundValueOps(seckillGoods.getId()).set(seckillGoods.getStockCount().toString());
            }
        }
        return seckillList;
    }

    @Override
    public TbSeckillGoods findSeckillGoodsFromRedis(Long id) {
        return (TbSeckillGoods)redisTemplate.boundHashOps(SeckillConstant.SECKILLLIST).get(id);
    }

    /**
     * 生成订单
     * @param id
     * @param userId
     */
    @Override
    public void createOrder(Long id, Long userId) {
         redisTemplate.setValueSerializer(new StringRedisSerializer());
        //从redis中查询出秒杀的商品
        TbSeckillGoods seckillGoods = (TbSeckillGoods) redisTemplate.boundHashOps(SeckillConstant.SECKILLLIST).get(id);
        if(null == seckillGoods){//缓存中没有此商品
            throw new RuntimeException("商品不存在");
        }
        //校验时间 当前时间是否小于秒杀结束的时间
        if(seckillGoods.getEndTime().getTime() - new Date().getTime() < 0){
            throw new RuntimeException("秒杀已结束");
        }
        //取出库存
       // Integer stockCount = Integer.parseInt(redisTemplate.boundValueOps(id).get().toString());
        //Integer.parseInt(redisTemplate.bo)
        String str =redisTemplate.boundValueOps(id).get()+"";
        Integer stockCount=Integer.parseInt(str);
        System.out.println("取出库存:"+stockCount);
        //没有库存
        if(stockCount <= 0){
            throw new RuntimeException("商品已售罄");
        }
        /////           减库存 生成订单      /////
        //seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);
        //将减过的库存放入缓存中
        //redisTemplate.boundHashOps(SeckillConstant.SECKILLLIST).put(id,seckillGoods);
        //库存-1
        Long decrement = redisTemplate.boundValueOps(id).decrement();
        //同步seckillGoods
        seckillGoods.setStockCount(decrement.intValue());
        redisTemplate.boundHashOps(SeckillConstant.SECKILLLIST).put(id,seckillGoods);
        //防止出现两个 0 的情况
        if(decrement.intValue() == 0){
            seckillGoodsMapper.updateByPrimaryKey(seckillGoods);//更新一下数据库 库存为0
            redisTemplate.boundHashOps(SeckillConstant.SECKILLLIST).delete(id);//删除redis
        }
        //保存订单 mq异步生成订单
        Map<String,Long> map = new HashMap<>();
        map.put("seckillId",seckillGoods.getId());
        map.put("userId",userId);
        rocketMQTemplate.convertAndSend("createOrder",map);
//        TbSeckillOrder seckillOrder = new TbSeckillOrder();
//        seckillOrder.setUserId(userId.toString());
//        seckillOrder.setStatus("0");//待支付
//        seckillOrder.setSellerId(seckillGoods.getSellerId());
//        seckillOrder.setSeckillId(seckillGoods.getId());
//        seckillOrder.setMoney(seckillGoods.getCostPrice());
//        seckillOrder.setCreateTime(new Date());
//        seckillOrder.setId(idWorker.nextId());
//        seckillOrderMapper.insertSelective(seckillOrder);
//        //redis存放当前用户待支付的商品订单数据
//        redisTemplate.boundHashOps(SeckillConstant.SECKILLORDER).put(userId,seckillOrder);
    }

    /**
     * 从redis中查询订单
     * @param id
     * @return
     */
    @Override
    public TbSeckillOrder findOrderFromRedis(Long id) {
        return (TbSeckillOrder) redisTemplate.boundHashOps(SeckillConstant.SECKILLORDER).get(id);
    }

    /**
     * 更改缓存中订单的状态并同步到数据库
     * @param userId
     */
    @Override
    public void updateOrderByUserId(String userId) {
        TbSeckillOrder seckillOrder = (TbSeckillOrder)redisTemplate.boundHashOps(SeckillConstant.SECKILLORDER).get(Long.parseLong(userId));
        seckillOrder.setStatus("1");//已支付
        redisTemplate.boundHashOps(SeckillConstant.SECKILLORDER).put(Long.parseLong(userId),seckillOrder);
        //同步数据库
        seckillOrderMapper.updateByPrimaryKeySelective(seckillOrder);

    }
}
